send X-Deeplake-Client: hivemind/<version> on deeplake-api calls#74
Merged
send X-Deeplake-Client: hivemind/<version> on deeplake-api calls#74
Conversation
The deeplake-api backend reads X-Deeplake-Client to attribute traffic for analytics (signup_source, login_source, daily retention rollup). Without the header, hivemind requests look identical to the generic cli_device_flow and are invisible in PostHog. - Add src/utils/client-header.ts with deeplakeClientHeader() using a build-time __HIVEMIND_VERSION__ define; dev runs fall back to "dev" so tsx/vitest don't crash on the undefined symbol. - Extend esbuild.config.mjs: define __HIVEMIND_VERSION__ for the CC and Codex bundles (openclaw already had an analogous define for its own version). - Apply the header at every outbound fetch site: DeepLakeAPI (query + listTables), commands/auth.ts (whoami / orgs / workspaces / device-code / device-token), and both wiki-worker.ts entry points. - Rebuild CC + Codex bundles so the shipped plugin carries the version literal baked in. No PostHog SDK in hivemind; backend does all analytics.
Contributor
Coverage ReportScope: files changed in this PR. Enforced threshold: 90% per metric (per file via
File Coverage — 5 files changed
Generated for commit 33eaf42. |
Comment on lines
+15
to
+20
| function pluginVersion(): string { | ||
| try { | ||
| if (typeof __HIVEMIND_VERSION__ === "string" && __HIVEMIND_VERSION__) { | ||
| return __HIVEMIND_VERSION__; | ||
| } | ||
| } catch { /* reference error in unbundled dev → fall through */ } |
There was a problem hiding this comment.
The try/catch around typeof __HIVEMIND_VERSION__ is unnecessary and the comment is incorrect — typeof never throws a ReferenceError in JavaScript; it specifically returns "undefined" for undeclared identifiers. The catch block will never execute. Drop the try/catch wrapper.
Suggested change
| function pluginVersion(): string { | |
| try { | |
| if (typeof __HIVEMIND_VERSION__ === "string" && __HIVEMIND_VERSION__) { | |
| return __HIVEMIND_VERSION__; | |
| } | |
| } catch { /* reference error in unbundled dev → fall through */ } | |
| function pluginVersion(): string { | |
| if (typeof __HIVEMIND_VERSION__ === "string" && __HIVEMIND_VERSION__) { | |
| return __HIVEMIND_VERSION__; | |
| } | |
| return "dev"; | |
| } |
…tch too OpenClaw is the same product as hivemind analytics-wise (same install base per user, same retention story), so it sends the same "hivemind/<version>" value via the shared helper. Only one outbound deeplake-api call (POST /users/me/tokens) needed the change; openclaw already has __HIVEMIND_VERSION__ defined by esbuild so no config changes. openclaw/dist/ is gitignored; rebuilds at release time.
# Conflicts: # openclaw/src/index.ts
typeof on an undeclared identifier returns "undefined", it never throws ReferenceError. The try/catch wrapper around the __HIVEMIND_VERSION__ guard was dead code (caught block could never execute). Replace with a plain typeof check + clearer comment explaining why the guard exists. Also rebuilds CC + Codex bundles after merging origin/main so the shipped artifacts reflect the new dist/ output. Marketplace bundle version stays in sync with package.json (now 0.6.48).
The post-substitution bundle had an always-true conditional:
if ("0.6.48") { return "0.6.48"; }
Useless at runtime and confusing on read.
Root cause: source code wrote a typeof guard so vitest (where esbuild's
define hadn't run) could fall back to "dev" without a ReferenceError.
Better fix: mirror the esbuild define in vitest.config.ts so tests also
get __HIVEMIND_VERSION__ substituted (with the literal "dev"), then drop
the guard at the source. Bundles now emit a clean
return \`hivemind/\${"0.6.48"}\`;
which becomes "hivemind/0.6.48" at runtime with no dead branches.
efenocchi
approved these changes
Apr 28, 2026
kaghni
added a commit
that referenced
this pull request
Apr 28, 2026
…ed-npx-installer
Resolves the same three conflicts as the previous main-merge:
- package.json: keep our @deeplake/hivemind name + publishConfig/files/
bin additions; take main's 0.6.49 version so post-merge auto-bump
advances to 0.6.50 cleanly.
- openclaw/package.json: same — keep scoped name, take 0.6.49.
- package-lock.json: regenerated via 'npm install' on top of main's
lockfile.
Side effects from main's 7 new commits (auto-merged, no manual work):
- PR #74 (X-Deeplake-Client header): adds src/utils/client-header.ts
and threads it through src/deeplake-api.ts, src/commands/auth.ts,
src/hooks/wiki-worker.ts, src/hooks/codex/wiki-worker.ts, plus the
openclaw bundle's own fetch path.
- vitest.config.ts: per-file thresholds for client-header.ts.
- 0.6.49 version bump propagated across plugin.json / marketplace.json
/ claude-code/.claude-plugin/plugin.json / codex/package.json /
openclaw/openclaw.plugin.json.
Verified post-merge: npm run ci -> 1107/1107 pass; verify-install.sh ->
22/22 PASS across all 6 agents; build clean (9 CC + 8 Codex + 6 Cursor
+ 6 Hermes + 1 OpenClaw + 1 MCP + 1 CLI bundle).
kaghni
added a commit
that referenced
this pull request
Apr 28, 2026
…ation Coverage on src/commands/auth.ts went from 0% → 100% lines / 96% statements / 99% branches / 81% functions. The PR coverage report on #74 was flagging auth.ts as 0/0/0/0 because the file had no direct unit tests on main even though every CC + Codex + openclaw fetch path goes through it. Test scope: - decodeJwtPayload: well-formed, malformed-segments, malformed-base64 - credential storage: load (missing / valid / corrupt), save (creates config dir on first write, skips when present), delete (true / false) - API helpers (apiGet/apiPost/apiDelete) covering the new X-Deeplake-Client + X-Activeloop-Org-Id header injection plus !ok failure modes - listOrgs / listMembers / removeMember / inviteMember / listWorkspaces including both {data: [...]} and bare-array response shapes - switchOrg / switchWorkspace including the "not logged in" guard - device flow: requestDeviceCode, pollForToken (success, pending, slow_down, expired_token, access_denied, unrecognized 400, non-400), deviceFlowLogin (orchestration + browser-open failure + deadline expiry + interval-fallback + linux/win32 platform branches) - login: full single-org and multi-org orchestration plus the email-prefix and "unknown" userName fallbacks Mocks node:fs / node:os / node:child_process / global.fetch only at the boundaries — the real auth.ts logic runs unchanged. Adds the file to vitest.config.ts per-file thresholds (90/90/80/90) so coverage can't regress later.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
X-Deeplake-Client: hivemind/<version>header on every outbound request to deeplake-api, so the backend can attribute hivemind traffic for analytics (signup source, login source, daily retention rollup).src/utils/client-header.tswith a singledeeplakeClientHeader()helper. Version is injected at bundle time via an esbuild__HIVEMIND_VERSION__define (same pattern openclaw already uses for its own version). Dev / tsx / vitest runs fall back to"dev"so nothing crashes without a bundle.DeepLakeAPI(query + listTables),commands/auth.ts(whoami / orgs / workspaces / device-code / device-token), and bothwiki-worker.tsentry points (CC + Codex).claude-code/bundle/andcodex/bundle/— grep confirms the version literal + header template both land in every shipped bundle.No PostHog SDK added to hivemind. All analytics stay server-side in deeplake-api (PR activeloopai/deeplake-api#193).
Test plan
npm run typecheckcleannpm test— all 966 tests passnpm run buildproduces bundles; grep confirms"0.6.45"+`hivemind/${pluginVersion()}`are present in CC + Codex bundlesrequestDeviceCode()emits the header (confirmedX-Deeplake-Client: hivemind/devin unbundled dev; bundle path getshivemind/0.6.45)login_completedwithlogin_source: hivemind,hivemind_version: 0.6.45sessionstable, the next 00:05 UTC rollup emitshivemind_daily_activewith matchingsessions_count